Add go-widgets → PDF bridge (raster + vector) - #2
Merged
Conversation
Bridge any github.com/go-widgets/toolkit widget tree onto a PDF page so a
UI can be "printed"/exported to PDF.
- AddWidget (raster): lays the tree out at the target size, renders it
through a go-widgets/painter PixelPainter into an RGBA buffer, and places
the result as an image XObject at the target rect. Prints any UI exactly
as it draws on screen.
- AddWidgetVector (vector): a painter.Painter (+ Clipper) implementation
that emits PDF vector operators (fills, strokes, rounded-corner Béziers,
1x1 pixels, clip) instead of pixels. Text drawn through the toolkit's
built-in bitmap font reaches the painter's Text primitive and becomes
real, selectable Type0 PDF text. Needs a WidgetOptions.Font.
- WidgetOptions{Theme, Scale, Font} with sensible defaults (DefaultLight,
DefaultWidgetScale=2). Read-only dependency on toolkit + painter; no
changes to go-widgets.
Tests build a real widget tree (Container + prominent Button + Label),
export to PDF and re-open with rsc.io/pdf as an independent oracle,
asserting the image XObject dimensions + painted pixels (raster) and the
Type0 font + text/fill/stroke/clip operators (vector). Exact 100%
statement coverage; go vet clean; builds on the 6 64-bit arches + wasm +
darwin + windows.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a go-widgets → PDF bridge so any
github.com/go-widgets/toolkitwidget tree can be "printed"/exported to a PDF. A read-only dependency ontoolkit+painteris added; go-widgets is not modified.API
(*Page) AddWidget(root toolkit.Widget, rect Rect, opts *WidgetOptions) error— raster. Lays the tree out at the target size, renders it through apainter.NewPixelPainter+root.Draw, and places the RGBA result as an image XObject atrect. Prints any UI exactly as it draws on screen.(*Page) AddWidgetVector(root toolkit.Widget, rect Rect, opts *WidgetOptions) error— vector. Apainter.Painter(+painter.Clipper) implementation that emits PDF vector operators (fills, strokes, rounded-corner Béziers, 1×1 pixels, clip) instead of pixels. Text drawn through the toolkit's built-in bitmap font reaches the painter'sTextprimitive and becomes real, selectable Type0 PDF text. RequiresWidgetOptions.Font.WidgetOptions{Theme, Scale, Font}with defaults (DefaultLight,DefaultWidgetScale = 2).Both levels achieved
Raster (must) and vector (stretch) are both implemented — the
painter.Painterinterface is only 7 methods + optional 2-methodClipper, small enough to implement cleanly, and the toolkit's bitmap font already delegates top.Textfor any non-PixelPainterback-end, which the vector painter turns into selectable PDF text.Proof
Tests build a real widget tree (
Container+ prominentButton+Label), export to PDF, and re-open with the independentrsc.io/pdfreader as an oracle:/Subtype /Image, itsWidth/Height,/Im0 Doin the content stream, and that decoded samples contain painted (non-black) pixels;Tj), fill (f), stroke (S), Bézier (c) and clip (W) operators in the content stream.Gate
CGO_ENABLED=0,go 1.26.4.go vetclean, gofmt clean (new files).js/wasm+ darwin + windows.🤖 Generated with Claude Code